package com.newsmanagement.service.impl;

import cn.hutool.core.text.CharSequenceUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.newsmanagement.domain.dto.NodeInfoPageDto;
import com.newsmanagement.domain.pojo.NodeInfo;
import com.newsmanagement.domain.pojo.PageBean;
import com.newsmanagement.domain.vo.NodeProvVo;
import com.newsmanagement.domain.vo.NodeTypeNameVo;
import com.newsmanagement.domain.vo.NodeTypeVo;
import com.newsmanagement.enums.EntTypeEnum;
import com.newsmanagement.exceptions.InsertFailedException;
import com.newsmanagement.exceptions.UpdateFailedException;
import com.newsmanagement.exceptions.UsernamePasswordException;
import com.newsmanagement.mapper.NodeInfoMapper;
import com.newsmanagement.service.NodeInfoService;
import com.newsmanagement.utils.JwtUtil;
import com.newsmanagement.utils.Md5Util;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Service;

import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * @author adim
 * @description 针对表【node_info(节点企业信息表)】的数据库操作Service实现
 * @createDate 2025-10-09 13:57:08
 */
@Service
public class NodeInfoServiceImpl extends ServiceImpl<NodeInfoMapper, NodeInfo>
        implements NodeInfoService {

    @Autowired
    private NodeInfoMapper nodeInfoMapper;

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    /**
     * 节点企业登录
     *
     * @param nodeInfo
     * @return
     */
    @Override
    public String nodeLogin(NodeInfo nodeInfo) {
        //查找这个节点账号是否存在
        LambdaQueryWrapper<NodeInfo> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(nodeInfo.getCode() != null, NodeInfo::getCode, nodeInfo.getCode());
        NodeInfo newNodeInfo = nodeInfoMapper.selectOne(queryWrapper);

        //判断用户是否存在
        if (newNodeInfo == null) {
            throw new UsernamePasswordException("该节点企业不存在");
        }
        //判断密码是否正确  u对象中的password是密文
        if (Md5Util.getMD5String(nodeInfo.getPassword()).equals(newNodeInfo.getPassword())) {
            //登录成功
            Map<String, Object> claims = new HashMap<>();
            claims.put("id", newNodeInfo.getNodeId());
            claims.put("username", newNodeInfo.getCode());
            String token = JwtUtil.genToken(claims);
            //把token存储到redis中
            ValueOperations<String, String> operations = stringRedisTemplate.opsForValue();
            operations.set(token, token, 1, TimeUnit.HOURS);
            return token;
        }
        return null;
    }


    @Override
    public PageBean<NodeInfo> pageNodeInfo(NodeInfoPageDto nodeInfoPageDto) {
        // 创建分页对象，添加参数校验
        int pageNum = nodeInfoPageDto.getPageNum() <= 0 ? 1 : nodeInfoPageDto.getPageNum();
        int pageSize = nodeInfoPageDto.getPageSize() <= 0 ? 10 : nodeInfoPageDto.getPageSize();

        Page<NodeInfo> page = new Page<>(pageNum, pageSize);

        // 构建查询条件
        LambdaQueryWrapper<NodeInfo> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.like(CharSequenceUtil.isNotBlank(nodeInfoPageDto.getName()), NodeInfo::getName, nodeInfoPageDto.getName())
                .eq(nodeInfoPageDto.getType() != null, NodeInfo::getType, nodeInfoPageDto.getType())
                .like(CharSequenceUtil.isNotBlank(nodeInfoPageDto.getProvName()), NodeInfo::getProvName, nodeInfoPageDto.getProvName())
                .like(CharSequenceUtil.isNotBlank(nodeInfoPageDto.getCityName()), NodeInfo::getCityName, nodeInfoPageDto.getCityName());

        // 执行分页查询
        page = this.page(page, queryWrapper);

        // 封装返回结果
        PageBean<NodeInfo> pageBean = new PageBean<>();
        pageBean.setTotal(page.getTotal());
        pageBean.setRows(page.getRecords());
        return pageBean;
    }


    @Override
    public boolean add(NodeInfo nodeInfo) {
        // 数据非空校验
        if (nodeInfo == null) {
            throw new InsertFailedException("数据不能为空");
        }

        // 密码非空校验
        if (CharSequenceUtil.isEmpty(nodeInfo.getPassword())) {
            throw new InsertFailedException("密码不能为空");
        }

        // 企业编码非空校验
        if (CharSequenceUtil.isEmpty(nodeInfo.getCode())) {
            throw new InsertFailedException("企业编码不能为空");
        }

        // 根据不同类型进行字段校验
        switch (nodeInfo.getType()) {
            case 1: // BREEDING_ENT - 养殖企业
                if (CharSequenceUtil.isEmpty(nodeInfo.getEpId()) || CharSequenceUtil.isEmpty(nodeInfo.getEiaId())) {
                    throw new InsertFailedException("养殖企业必须填写动物防疫条件合格证编号和环境影响评价资质证书编号");
                }
                break;
            case 2: // SLAUGHTERING_ENT - 屠宰企业
                if (CharSequenceUtil.isEmpty(nodeInfo.getEiaId())) {
                    throw new InsertFailedException("屠宰企业必须填写环境影响评价资质证书编号");
                }
                break;
            case 3: // FARMING_ENT - 批发商
                if (CharSequenceUtil.isEmpty(nodeInfo.getCirId()) || CharSequenceUtil.isEmpty(nodeInfo.getFbId())) {
                    throw new InsertFailedException("批发商必须填写食品流通许可证编号和食品经营许可证编号");
                }
                break;
            case 4: // MARKET_ENT - 零售商
                if (CharSequenceUtil.isEmpty(nodeInfo.getFbId())) {
                    throw new InsertFailedException("零售商必须填写食品经营许可证编号");
                }
                break;
            default:
                throw new InsertFailedException("未知的企业类型");
        }

        // 查询是否已存在该企业编码
        LambdaQueryWrapper<NodeInfo> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(NodeInfo::getCode, nodeInfo.getCode());
        NodeInfo existingNode = this.getOne(lambdaQueryWrapper);
        if (existingNode != null) {
            throw new InsertFailedException("该企业编码已存在");
        }

        // 密码加密存储
        nodeInfo.setPassword(Md5Util.getMD5String(nodeInfo.getPassword()));

        // 执行保存操作
        boolean result = this.save(nodeInfo);
        if (!result) {
            throw new InsertFailedException("节点企业信息保存失败");
        }

        return result;
    }

    /**
     * 获取节点信息
     *
     * @param code
     * @return
     */
    @Override
    public NodeInfo getNodeInfo(String code) {
        LambdaQueryWrapper<NodeInfo> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(CharSequenceUtil.isNotBlank(code), NodeInfo::getCode, code);
        return this.getOne(queryWrapper);
    }

    /**
     * 修改节点信息
     *
     * @param nodeInfo
     * @return
     */
    @Override
    public boolean updateNodeInfo(NodeInfo nodeInfo) {
        //如果要重置密码的话
        if (CharSequenceUtil.isNotBlank(nodeInfo.getPassword())) {
            nodeInfo.setPassword(Md5Util.getMD5String(nodeInfo.getPassword()));
        }
        // 要对拿到的code进行查询，要保证唯一，但需要排除自
        LambdaQueryWrapper<NodeInfo> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(NodeInfo::getCode, nodeInfo.getCode())
                .ne(NodeInfo::getNodeId, nodeInfo.getNodeId()); // 排除自身
        NodeInfo existingNode = this.getOne(queryWrapper);
        if (existingNode != null) {
            throw new UpdateFailedException("该编码已存在");
        }

        return nodeInfoMapper.updateNodeInfo(nodeInfo) > 0;
    }

    /**
     * 删除节点信息d
     *
     * @param id
     * @return
     */
    @Override
    public Boolean removeNodeInfoById(Integer id) {
        return nodeInfoMapper.removeNodeInfoById(id) > 0;
    }

    /**
     * 获取节点趋势
     *
     * @return
     */
    @Override
    public Map<String, Object> getNodeTrend() {
        // 创建返回结果map
        Map<String, Object> result = new HashMap<>();

        // 生成最近12个月的月份数据
        List<String> months = new ArrayList<>();
        List<Integer> registerCounts = new ArrayList<>();

        // 获取当前日期
        LocalDate now = LocalDate.now();

        // 查询最近12个月的企业注册数据
        for (int i = 11; i >= 0; i--) {
            // 计算每个月的日期
            LocalDate monthDate = now.minusMonths(i);
            String monthStr = monthDate.format(DateTimeFormatter.ofPattern("MM月"));
            months.add(monthStr);

            // 计算该月的第一天和下个月的第一天
            LocalDate startDate = monthDate.withDayOfMonth(1);
            LocalDate endDate = startDate.plusMonths(1);

            // 查询该月份的注册企业数量
            Integer count = nodeInfoMapper.countByMonth(startDate, endDate);
            registerCounts.add(count == null ? 0 : count);
        }

        // 构造返回数据
        result.put("xAxisData", months);
        result.put("seriesData", registerCounts);

        return result;
    }

    /**
     * 获取节点省份
     *
     * @return
     */
    @Override
    public List<NodeProvVo> getNodeProv() {
        return nodeInfoMapper.countByProvince();
    }

    /**
     * 获取节点类型
     *
     * @return
     */
    @Override
    public List<NodeTypeNameVo> getNodeType() {
        List<NodeTypeVo> nodeInfo = nodeInfoMapper.countByNodeType();
        List<NodeTypeNameVo> nodeTypeNameVos = new ArrayList<>();

        for (NodeTypeVo nodeTypeVo : nodeInfo) {
            NodeTypeNameVo nodeTypeNameVo = new NodeTypeNameVo();
            nodeTypeNameVo.setCount(nodeTypeVo.getCount());

            // 根据类型值获取对应的枚举描述
            EntTypeEnum entTypeEnum = EntTypeEnum.fromValue(nodeTypeVo.getType());
            if (entTypeEnum != null) {
                nodeTypeNameVo.setTypeName(entTypeEnum.getDesc());
            } else {
                nodeTypeNameVo.setTypeName("未知类型");
            }

            nodeTypeNameVos.add(nodeTypeNameVo);
        }

        return nodeTypeNameVos;
    }


    /**
     * 获取所有省份信息（去重）
     *
     * @return 省份列表（包含provId和provName）
     */
    @Override
    public List<NodeInfo> getProvinces() {
        try {
            LambdaQueryWrapper<NodeInfo> queryWrapper = new LambdaQueryWrapper<>();
            // 只查询非空的省份信息并去重
            queryWrapper.select(NodeInfo::getProvId, NodeInfo::getProvName)
                    .isNotNull(NodeInfo::getProvId)
                    .isNotNull(NodeInfo::getProvName)
                    .groupBy(NodeInfo::getProvId, NodeInfo::getProvName); // 分组去重

            List<NodeInfo> provinces = baseMapper.selectList(queryWrapper);
            System.out.println("查询到省份数据: " + provinces.size() + " 条");

            // 为了确保前端能正确显示，我们为每个NodeInfo对象设置nodeId为provId
            for (NodeInfo province : provinces) {
                if (province.getNodeId() == null && province.getProvId() != null) {
                    province.setNodeId(province.getProvId()); // 临时设置nodeId为provId，确保前端能正确识别
                }
            }

            return provinces;
        } catch (Exception e) {
            System.err.println("获取省份信息时发生错误: " + e.getMessage());
            e.printStackTrace();
            throw new RuntimeException("获取省份信息失败: " + e.getMessage(), e);
        }
    }

    /**
     * 根据省份ID获取城市信息（去重）
     *
     * @param provId 省份ID
     * @return 城市列表（包含cityId和cityName）
     */
    @Override
    public List<NodeInfo> getCitiesByProvId(Integer provId) {
        try {
            LambdaQueryWrapper<NodeInfo> queryWrapper = new LambdaQueryWrapper<>();
            // 根据省份ID查询非空的城市信息并去重
            queryWrapper.select(NodeInfo::getCityId, NodeInfo::getCityName)
                    .eq(NodeInfo::getProvId, provId)
                    .isNotNull(NodeInfo::getCityId)
                    .isNotNull(NodeInfo::getCityName)
                    .groupBy(NodeInfo::getCityId, NodeInfo::getCityName); // 分组去重

            List<NodeInfo> cities = baseMapper.selectList(queryWrapper);
            System.out.println("查询到城市数据: " + cities.size() + " 条，省份ID: " + provId);

            // 为每个NodeInfo对象设置nodeId为cityId
            for (NodeInfo city : cities) {
                if (city.getNodeId() == null && city.getCityId() != null) {
                    city.setNodeId(city.getCityId()); // 临时设置nodeId为cityId
                }
            }

            return cities;
        } catch (Exception e) {
            System.err.println("获取城市信息时发生错误: " + e.getMessage());
            e.printStackTrace();
            throw new RuntimeException("获取城市信息失败: " + e.getMessage(), e);
        }
    }

    /**
     * 根据地区获取屠宰企业（type=2）
     *
     * @param provId 省份ID
     * @param cityId 城市ID
     * @return 屠宰企业列表
     */
    @Override
    public List<NodeInfo> getSlaughterByArea(Integer provId, Integer cityId) {
        LambdaQueryWrapper<NodeInfo> queryWrapper = new LambdaQueryWrapper<>();
        // 查询类型为屠宰企业（type=2）且匹配地区的企业
        queryWrapper.eq(NodeInfo::getType, 2) // 2表示屠宰企业
                .eq(NodeInfo::getProvId, provId)
                .eq(NodeInfo::getCityId, cityId)
                .isNotNull(NodeInfo::getName); // 确保企业名称不为空
        return baseMapper.selectList(queryWrapper);
    }

    // ========== 新增的方法实现 ==========

    /**
     * 检查登录账号是否存在
     *
     * @param loginCode 登录账号
     * @return 是否存在
     */
    @Override
    public boolean checkLoginCodeExists(String loginCode) {
        LambdaQueryWrapper<NodeInfo> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(NodeInfo::getCode, loginCode);
        return this.count(queryWrapper) > 0;
    }

    /**
     * 根据企业类型统计数量
     *
     * @param type 企业类型 (1:养殖企业, 2:屠宰企业, 3:批发商, 4:零售商)
     * @return 数量
     */
    @Override
    public Long countByType(Integer type) {
        LambdaQueryWrapper<NodeInfo> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(NodeInfo::getType, type);
        return (long) this.count(queryWrapper);
    }

    /**
     * 根据省份统计数量
     *
     * @param province 省份名称
     * @return 数量
     */
    @Override
    public Long countByProvince(String province) {
        LambdaQueryWrapper<NodeInfo> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(CharSequenceUtil.isNotBlank(province), NodeInfo::getProvName, province);
        return (long) this.count(queryWrapper);
    }
}